package com.woniu.product.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.common.dto.*;
import com.woniu.common.util.GetUserInfoUtil;
import com.woniu.common.util.PageParam;
import com.woniu.common.util.ResponseData;
import com.woniu.product.feign.CouponFeign;
import com.woniu.product.feign.SkuFeign;
import com.woniu.product.feign.UserFeign;
import com.woniu.product.mapper.TOrderMapper;
import com.woniu.product.pojo.TOrder;
import com.woniu.product.pojo.TOrderDetail;
import com.woniu.product.service.TOrderDetailService;
import com.woniu.product.service.TOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.SneakyThrows;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.woniu.common.constant.MqConstant.Exchange.SKU_ORDER_EXCHANGE;
import static com.woniu.common.constant.MqConstant.RoutingKey.*;
import static com.woniu.common.util.SendMessageUtil.sendMsg;

/**
 * @author zyq
 * @description 针对表【t_order(订单)】的数据库操作Service实现
 * @createDate 2024-05-21 19:37:20
 */
@Service
public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder>
        implements TOrderService {

    @Autowired
    private TOrderDetailService orderDetailService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Value("${snowflake.workerId}")
    private long workerId;
    @Value("${snowflake.datacenterId}")
    private long datacenterId;

    @Autowired
    private SkuFeign skuFeign;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private CouponFeign couponFeign;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRechargeOrder(String phone, BigDecimal price, Long orderNum, BigDecimal totalPrice) {


        TOrder order = new TOrder();
        order.setID(orderNum);
        order.setIdStr(orderNum.toString());
        order.setTotalPrice(totalPrice);
        order.setPayPrice(price);
        order.setStatus(1);
        order.setUserTelephone(phone);
        order.setTypeId(1);
        order.setSourceId(4);
        order.setCreateTime(new Date());
        order.setOrderServiceTypeId(13);
        order.setIsInvoice(0);

        Long orderNum1 = IdUtil.getSnowflake(workerId, datacenterId).nextId();
        TOrderDetail orderDetail = new TOrderDetail();
        orderDetail.setId(orderNum1);
        orderDetail.setOrderNum(orderNum);
        orderDetail.setItemPrice(totalPrice);
        orderDetail.setPayMoney(price);
        orderDetail.setOrderServiceId(13);
        orderDetail.setStatus(1);
        orderDetail.setOrderTypeId(1);
        orderDetail.setUserTelephone(phone);
        orderDetail.setBuyNum(1);

        save(order);
        orderDetailService.save(orderDetail);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rollbackRechargeOrder(Long orderNum, String phone, BigDecimal price) {

        TOrder order = getById(orderNum);


        TOrderDetail orderDetail = orderDetailService.lambdaQuery()
                .eq(TOrderDetail::getOrderNum, orderNum)
                .one();

        if (ObjectUtils.isEmpty(order) || 1 != order.getStatus()) {
            return;
        }

        //4.删除订单
        order.setStatus(5);
        order.setPayPrice(BigDecimal.valueOf(0));
        orderDetail.setStatus(5);
        orderDetail.setPayMoney(BigDecimal.valueOf(0));
        updateById(order);

        orderDetailService.updateById(orderDetail);
    }

    @Override
    public ResponseData<?> queryOrderByOrderNum(String orderNum) {

        TOrder order = getById(orderNum);

        return new ResponseData<>().ok(order);
    }

    @Override
    public ResponseData<?> queryAllOrder(PageParam<TOrder> pageParam) {
        // 创建Page对象，第一个参数是当前页，第二个参数是每页的数量
        Page<TOrder> page = new Page<>(pageParam.getPageNum(), pageParam.getPageSize());
        // 使用Page对象进行分页查询
        IPage<TOrder> iPage = lambdaQuery().eq(TOrder::getStatus, 4)
                .eq(TOrder::getUserTelephone, pageParam.getParam().getUserTelephone())
                .eq(TOrder::getTypeId, 1).page(page);

        return new ResponseData<>().ok(iPage);
    }

    @Override
    public ResponseData<?> updateIsInvoiceStatus(String orderNum) {

        lambdaUpdate().setSql("is_invoice = 1").eq(TOrder::getIdStr, orderNum).update();

        return new ResponseData<>().ok();
    }

    @Override
    public ResponseData<?> addSkuOrder(SkuOrderDto skuOrderDto, Long orderNum) {
        ;
        //判断库存是否不足
        //首先获得新的想要购买的数量
        List<CartItemDto> cartItems = skuOrderDto.getItems();
        List<CartDto> shops = new ArrayList<>();
        for (CartItemDto cartItem : cartItems) {
            //通过skuId查下面库存
            Long skuStore = skuFeign.querySkuCount(cartItem.getSkuId()).getSkuStore();
            if (cartItem.getQuantity() > skuStore.intValue()) {//如果有不足的
                return new ResponseData<>(500,
                        skuFeign.querySkuCount(cartItem.getSkuId()).getSpuName() + "目前库存不足,现有量:"
                                + skuStore, null);
            }
            //如果库存够,修改购物车商品数量和总额
            BigDecimal totalPrice = BigDecimal.valueOf(cartItem.getQuantity())
                    .multiply(skuFeign.querySkuCount(cartItem.getSkuId()).getSkuPrice());
            skuFeign.updateCartCount(cartItem.getId(), (long) cartItem.getQuantity(), totalPrice);

            shops.add(skuFeign.queryCartById(cartItem.getId()));
        }

        //生成订单表
        TOrder orderDto = new TOrder();
        orderDto.setID(orderNum);
        orderDto.setStatus(101);
        orderDto.setTypeId(2);
        orderDto.setUserTelephone(skuOrderDto.getPhone());
        orderDto.setSourceId(1);
        orderDto.setCreateTime(new Date());
        orderDto.setOrderServiceTypeId(3);
        orderDto.setOrderPayId(1);
        orderDto.setTotalPrice(skuOrderDto.getTotalPrice());
        orderDto.setProvince(skuOrderDto.getProvince());
        orderDto.setAddressId(skuOrderDto.getAddressId().intValue());
        orderDto.setPayPrice(skuOrderDto.getTotalPrice());
        orderDto.setIsInvoice(0);
        orderDto.setIdStr(orderNum.toString());
        UserAddrDto addr = userFeign.getAddr(skuOrderDto.getAddressId());
        orderDto.setReceiver(addr.getReceiver());
        orderDto.setReceiverPhone(addr.getReceiverPhone());
        save(orderDto);


        //生成子订单表
        //购物车商品查类型,如果是优惠卷这个类型的
        CouPonDto couPonDto = couponFeign.queryCouponById(skuOrderDto.getCouponId());
        List<TOrderDetail> orderDetail = new ArrayList<>();
        if (skuOrderDto.getCouponId() == 0) { //没用优惠卷
            for (CartDto shop : shops) {
                TOrderDetail detailDto = new TOrderDetail();
                Long orderNumDb = IdUtil.getSnowflake(workerId, datacenterId).nextId();
                detailDto.setId(orderNumDb);
                detailDto.setOrderNum(orderNum);
                detailDto.setStatus(101);
                detailDto.setItemId(shop.getSkuId().intValue());
                detailDto.setItemName(shop.getSkuName());
                detailDto.setItemPrice(shop.getBuyPrice());
                detailDto.setBuyNum(shop.getBuyNum());
                detailDto.setUserTelephone(skuOrderDto.getPhone());
                detailDto.setPayMoney(shop.getTotalPrice());
                detailDto.setOrderTypeId(2);
                detailDto.setOrderServiceId(3);
                detailDto.setCreateTime(new Date());
                SkuDto skuDto = skuFeign.querySkuType(shop.getSkuId());
                detailDto.setItemPlace(skuDto.getPlace());
                detailDto.setIsremark(0);
                orderDetail.add(detailDto);
            }
        } else {
            for (CartDto shop : shops) {
                TOrderDetail detailDto = new TOrderDetail();
                Long orderNumDb = IdUtil.getSnowflake(workerId, datacenterId).nextId();

                detailDto.setId(orderNumDb);
                detailDto.setOrderNum(orderNum);
                detailDto.setStatus(101);
                detailDto.setItemId(shop.getSkuId().intValue());
                detailDto.setItemName(shop.getSkuName());
                detailDto.setItemPrice(shop.getBuyPrice());
                detailDto.setBuyNum(shop.getBuyNum());
                detailDto.setUserTelephone(skuOrderDto.getPhone());
                //如果商品类型和优惠券类型相同，将优惠券的折扣应用到这个商品
                SkuDto skuDto = skuFeign.querySkuType(shop.getSkuId());
                if (skuDto.getSortId().intValue() == couPonDto.getSortId()) {
                    BigDecimal bigDecimalDivisor = new BigDecimal(skuOrderDto.getCouponUsedItemCount().toString());
                    // 执行除法操作
                    BigDecimal result = couPonDto.getValue().divide(bigDecimalDivisor, 2, RoundingMode.HALF_UP);
                    detailDto.setPayMoney(shop.getTotalPrice().subtract(result));
                }
                detailDto.setOrderTypeId(2);
                detailDto.setOrderServiceId(3);
                detailDto.setCreateTime(new Date());
                detailDto.setItemPlace(skuDto.getPlace());
                detailDto.setIsremark(0);
                orderDetail.add(detailDto);
            }
        }

        orderDetailService.saveBatch(orderDetail);

        JSONObject shopJson = new JSONObject(1);
        shopJson.put("shops", shops);

        //修改商品库存
        sendMsg(redisTemplate, rabbitTemplate, SKU_ORDER_EXCHANGE, SKU_ROUTING_KEY, shopJson.toString());
        //skuFeign.updateStore(shops);

        //修改购物车状态
        sendMsg(redisTemplate, rabbitTemplate, SKU_ORDER_EXCHANGE, SHOPPINGCART_ROUTING_KEY, shopJson.toString());
        //skuFeign.updateCartStatus(shops);
        return new ResponseData<>().ok();
    }

    @Override
    public void rollbackSkuOrder(SkuOrderDto skuOrderDto, Long orderNum) {
        //已提交未支付15分钟的订单进行回滚操作
        //查看订单状态
        TOrder order = getById(orderNum);

        //订单状态为101则回滚
        if (ObjectUtils.isEmpty(order) || 101 != order.getStatus()) {
            return;
        }

        List<CartItemDto> cartItems = skuOrderDto.getItems();
        List<CartDto> shops = new ArrayList<>();
        for (CartItemDto cartItem : cartItems) {
            shops.add(skuFeign.queryCartById(cartItem.getId()));
        }

        JSONObject shopJson = new JSONObject(1);
        shopJson.put("shops", shops);
        //发送回滚商品信息
        sendMsg(redisTemplate, rabbitTemplate, SKU_ORDER_EXCHANGE, ROLLBACK_SKU_ROUTING_KEY, shopJson.toString());

        //发送回滚购物车信息
        sendMsg(redisTemplate, rabbitTemplate, SKU_ORDER_EXCHANGE, ROLLBACK_SHOPPINGCART_ROUTING_KEY, shopJson.toString());

        //订单和子订单改成115取消订单
        order.setStatus(115);
        updateById(order);
        List<TOrderDetail> tOrderDetails = orderDetailService.lambdaQuery()
                .eq(TOrderDetail::getOrderNum, orderNum)
                .list();
        List<TOrderDetail> list = new ArrayList<>();
        for (TOrderDetail tOrderDetail : tOrderDetails) {
            tOrderDetail.setStatus(115);
            list.add(tOrderDetail);
        }
        orderDetailService.updateBatchById(list);
    }


    @Override
    public ResponseData<?> updateStatus(String orderNum) {

        lambdaUpdate().setSql("status = 4")
                .eq(TOrder::getID,orderNum).update();

        TOrderDetail orderDetail = orderDetailService.lambdaQuery()
                .eq(TOrderDetail::getOrderNum, orderNum)
                .one();

        orderDetail.setStatus(4);
        orderDetailService.updateById(orderDetail);

        return new ResponseData<>().ok();
    }

    @Override
    public void addJifenRechargeOrder(String phone, Integer integral, Long orderNum) {


        TOrder order = new TOrder();
        order.setID(orderNum);
        order.setIdStr(orderNum.toString());
        order.setIntegral(integral);
        order.setStatus(1);
        order.setUserTelephone(phone);
        order.setTypeId(1);
        order.setSourceId(4);
        order.setCreateTime(new Date());

        order.setOrderServiceTypeId(13);
        order.setIsInvoice(0);

        TOrderDetail orderDetail = new TOrderDetail();
        orderDetail.setId(orderNum);
        orderDetail.setOrderNum(orderNum);
        orderDetail.setIntegral(integral);
        orderDetail.setOrderServiceId(13);
        orderDetail.setStatus(1);
        orderDetail.setOrderTypeId(1);
        orderDetail.setUserTelephone(phone);
        orderDetail.setBuyNum(1);

        save(order);
        orderDetailService.save(orderDetail);
    }

    @Override
    public void rollbackJifenRechargeOrder(Long orderNum, String phone, Integer integral) {
        TOrder order = getById(orderNum);

        TOrderDetail orderDetail = orderDetailService.getById(orderNum);

        if (ObjectUtils.isEmpty(order) || 1 != order.getStatus()) {
            return;
        }

        //4.删除订单
        order.setStatus(5);
        order.setIntegral(0);
        orderDetail.setStatus(5);
        orderDetail.setIntegral(0);
        updateById(order);

        orderDetailService.updateById(orderDetail);
    }

    @Override
    @SneakyThrows
    public ResponseData<?> addJifenSkuOrder(SkuOrderJifenDto skuOrderDto, Long orderNum) {
        //判断库存是否不足
        //首先获得新的想要购买的数量


        //通过skuId查下面库存
        Long skuStore = skuFeign.queryJifenSkuCount(skuOrderDto.getSkuId()).getSkuStore();
        if (skuOrderDto.getBuyNum() > skuStore.intValue()) {//如果有不足的
            return new ResponseData<>(500,
                    skuFeign.queryJifenSkuCount(skuOrderDto.getSkuId()).getSpuName() + "目前库存不足,现有量:"
                            + skuStore, null);
        }



        //生成订单表
        TOrder orderDto = new TOrder();
        orderDto.setID(orderNum);
        orderDto.setStatus(101);
        orderDto.setTypeId(2);
        orderDto.setUserTelephone(skuOrderDto.getPhone());
        orderDto.setSourceId(1);
        orderDto.setCreateTime(new Date());
        orderDto.setOrderServiceTypeId(3);
        orderDto.setOrderPayId(2);
        orderDto.setIntegral(skuOrderDto.getTotalIntegral());
        orderDto.setIsInvoice(0);
        orderDto.setIdStr(orderNum.toString());
        save(orderDto);


        //生成子订单表

        TOrderDetail detailDto = new TOrderDetail();
        Long orderNumDb = IdUtil.getSnowflake(workerId, datacenterId).nextId();
        detailDto.setId(orderNumDb);
        detailDto.setOrderNum(orderNum);
        detailDto.setStatus(101);
        detailDto.setItemId(skuOrderDto.getSkuId().intValue());

        detailDto.setItemName(skuOrderDto.getSkuName());

        detailDto.setBuyNum(skuOrderDto.getBuyNum());
        detailDto.setUserTelephone(skuOrderDto.getPhone());
        detailDto.setIntegral(skuOrderDto.getTotalIntegral());
        detailDto.setOrderTypeId(2);
        detailDto.setOrderServiceId(3);
        detailDto.setCreateTime(new Date());
        detailDto.setIsremark(0);

        orderDetailService.save(detailDto);

        return new ResponseData<>().ok();
    }

    @Override
    public void rollbackJifenSkuOrder(SkuOrderDto skuOrderDto, Long orderNum) {
        //已提交未支付15分钟的订单进行回滚操作
        //查看订单状态
        TOrder order = getById(orderNum);
        order.setUpdateTime(new Date());
        //订单状态为101则回滚
        if (ObjectUtils.isEmpty(order) || 101 != order.getStatus()) {
            return;
        }

        //订单和子订单改成115取消订单
        order.setStatus(115);

        updateById(order);
        TOrderDetail tOrderDetail = orderDetailService.lambdaQuery()
                .eq(TOrderDetail::getOrderNum, orderNum).one();
        tOrderDetail.setUpdateTime(new Date());
        tOrderDetail.setStatus(115);
        orderDetailService.updateById(tOrderDetail);
    }

}




